package com.njtoyo.taxi.admin.security.filter;

import com.google.common.base.Strings;
import com.njtoyo.taxi.admin.rest.wrapper.Identity;
import com.njtoyo.taxi.admin.security.TokenVerifier;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * @Author Dell
 * @Date 2021/6/9 17:10
 */
@WebFilter(filterName = "authFilter", urlPatterns = "/*")
@Slf4j
public class AuthenticationFilter implements Filter {

    @Autowired
    private TokenVerifier verifyToken;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String accessToken = getAccessToken(request);
        if (!Strings.isNullOrEmpty(accessToken)) {
            String token = verifyAccessToken(accessToken);

            Identity identity = verifyToken.verifyIdentityToken(token);
            if (Objects.isNull(identity)) {
                sendInvalidAccessTokenResponse(request, response);
                return;
            }

            if (identity.getIsExpired()){
                sendInvalidLoginTimeResponse(request,response);
                return;
            }

            request.setAttribute("identity", identity);
        } else {
            request.setAttribute("identity", null);
        }

        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }

    private void sendInvalidAccessTokenResponse(HttpServletRequest request, HttpServletResponse response) {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.addHeader(
                "WWW-Authenticate",
                "OAuth realm=\"njtoyo\", oauth_error=\"Invalid Access Token\"");
    }

    private void sendInvalidLoginTimeResponse(HttpServletRequest request, HttpServletResponse response) {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.addHeader(
                "WWW-Authenticate",
                "OAuth realm=\"njtoyo\", oauth_error=\"Invalid Login Time\"");
    }

    private String getAccessToken(HttpServletRequest request) {
        String headerValue = request.getHeader("Authorization");
        if (!Strings.isNullOrEmpty(headerValue)) {
            return headerValue;
        } else {
            return null;
        }
    }

    private String verifyAccessToken(String accessToken) {
        int firstSpaceIndex = accessToken.indexOf(" ");

        if (firstSpaceIndex == -1) {
            return null;
        }

        String authMethod = accessToken.substring(0, firstSpaceIndex).trim();
        String token = accessToken.substring(firstSpaceIndex).trim();

        if (!authMethod.equalsIgnoreCase("Bearer") || Strings.isNullOrEmpty(token)) {
            return null;
        }
        return token;
    }

}
